/////////////////////////////////////////////////////////////
// This file is used to add random noise for sample images
/////////////////////////////////////////////////////////////


#include <opencv2/opencv.hpp>
#include <string>

using namespace cv;
using namespace std;

double generateGaussianNoise(double mu, double sigma)  
{  
    //定义一个特别小的值  
    const double epsilon = numeric_limits<double>::min();//返回目标数据类型能表示的最逼近1的正数和1的差的绝对值  
    static double z1;  
    static bool flag = false;  
    flag = !flag;  
    if (!flag)  
        return z1*sigma + mu;  
    double u1, u2;   
    srand(cv::getTickCount());
    do  
    {  
        u1 = rand()*(1.0 / RAND_MAX);  
        u2 = rand()*(1.0 / RAND_MAX);  
    } while (u1 <= epsilon);  
    z1 = sqrt(-2.0*log(u1))*sin(2 * CV_PI * u2);  
    return z1*sigma + mu;  
}  

//为图像添加高斯噪声  
Mat addGaussianNoise(Mat& srcImage)  
{  
    Mat resultImage = srcImage.clone();    
    int channels = resultImage.channels();    //获取图像的通道  
    int nRows = resultImage.rows;   
      
    int nCols = resultImage.cols*channels;  
    //判断图像的连续性  
    if (resultImage.isContinuous())      
    {  
        nCols *= nRows;  
        nRows = 1;  
    }  
   RNG rng(getTickCount());
   double mu = rng.uniform(-1.0,2.0);  
    for (int i = 0; i < nRows; i++)  
    {  
        for (int j = 0; j < nCols; j++)  
        {    
            uchar val = cv::saturate_cast<uchar>(resultImage.ptr<uchar>(i)[j] + generateGaussianNoise(mu ,0.8) * 32);  
            resultImage.ptr<uchar>(i)[j] = val;  
        }  
    }  
    return resultImage;  
}  

int main(int argc, char** argv)
{
	// if(argc != 3){
	// 	cout << "Usage: IMAGE_NAME SAVE_NAME" << endl;
	// 	return -1;
	// }
	// cv::Mat img = cv::imread(argv[1]);

	// cv::Mat res = addGaussianNoise(img);
	// // cv::imshow("img",img);
	// // cv::imshow("res",res);
	// // cv::waitKey();
	cv::Mat all_black = cv::Mat::zeros(480,640,CV_8UC3);
	cv::imwrite("black.png",all_black);
	 // cv::imwrite(string(argv[2]),res);
	 // cout << string(argv[2]) + " written!" << endl;
	return 0;
}